#ifndef  PARSE_ABST_H
#define  PARSE_ABST_H 1

#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <uuid/uuid.h>
#include <sys/stat.h>

//static const char *BOX_TYPE_UUID 	 = "uuid";                   
//static const char *BOX_TYPE_ABST         = "abst";                   
//static const char *BOX_TYPE_ASRT   	 = "asrt";                   
//static const char *BOX_TYPE_AFRT 	 = "afrt";                   
//static const char *BOX_TYPE_AFRA	 = "afra";                   
//static const char *BOX_TYPE_MDAT	 = "mdat";                   
//static const char *BOX_TYPE_MOOF	 = "moof";                   
//static const char *EXTENDED_TYPE	 = "uuid";                   

static const unsigned int FIELD_SIZE_LENGTH  = 4;                      
static const unsigned int FIELD_TYPE_LENGTH  = 4;                      
static const unsigned int FIELD_LARGE_SIZE_LENGTH  = 8;                
static const unsigned int FIELD_EXTENDED_TYPE_LENGTH = 16;            


static const unsigned int FULL_BOX_FIELD_FLAGS_LENGTH = 3;
static const unsigned int AFRA_MASK_LONG_ID = 128;
static const unsigned int AFRA_MASK_LONG_OFFSET = 64;
static const unsigned int AFRA_MASK_GLOBAL_ENTRIES = 32;
                                                                       
static const unsigned int FLAG_USE_LARGE_SIZE = 1;                    



typedef struct boxinfo_s 
{
  u_int32_t    size;
  u_int8_t     *type;
} boxinfo_t;

typedef struct box_s 
{
  u_int64_t size;
  u_int8_t  *type;
  u_int32_t boxLength;	
} box_t;

typedef struct fullbox_s 
{
  box_t     box;
  u_int32_t version:1;
  u_int32_t flags:3;
} fullbox_t;

typedef struct segmentrunentry_s
{
  u_int32_t firstsegment;
  u_int32_t fragspersegment;
}segmentrunentry_t;

typedef struct segmentruntable_s 
{
  u_int32_t             size;
  u_int8_t      	*type;
  u_int32_t    		version:8;
  u_int32_t    		flags:24;
  u_int32_t    		qualityentrycount:8; 
  u_int8_t     		**qualitysegmentURLmodifiers;
  u_int32_t    		segmentrunentrycount; 
  segmentrunentry_t 	*segmentrunentry;
}segmentruntable_t;


typedef struct fragmentrunentry_s
{
  u_int32_t firstfrag;
  u_int64_t firstfragtimestamp;
  u_int32_t fragduration;
  u_int32_t discontinuityindicator:8;
} fragmentrunentry_t;

typedef struct fragmentruntable_s
{
  u_int32_t             size;
  u_int8_t      	*type;
  u_int32_t    		version:8;
  u_int32_t    		flags:24;
  u_int32_t 		timescale;
  u_int32_t    		qualityentrycount:8; 
  u_int8_t     		**qualitysegmentURLmodifiers;
  u_int32_t    		fragmentrunentrycount; 
  fragmentrunentry_t 	*fragmentrunentry;
} fragmentruntable_t; 

typedef struct abst_s
{
  char      *buff_b;
  long      len;
  char      *fragmentrunentrycount_p;
  size_t    fragmentrunentrycount_pos;
  u_int32_t lastfragidx;
  fullbox_t fullbox;
  u_int32_t bootstrapVersion;
  u_int32_t profile:2;
  u_int32_t live:1;
  u_int32_t update:1;
  u_int32_t reserved:4;
  u_int32_t timescale;
  u_int64_t currentmediatime;
  u_int64_t smptetimecodeoffset;
  u_int8_t  *movieidentifier;
  u_int32_t serverentrycount:8;
  u_int8_t  **serverbaseURLs;
  u_int32_t qualityentrycount:8;
  u_int8_t  **qualitysegmentURLmodifiers;
  u_int8_t  *drmdata;
  u_int8_t  *metadata;
  u_int32_t segmentcount:8;
  segmentruntable_t   *segmentruntables;
  u_int32_t fragmentcount:8;
  fragmentruntable_t  *fragmentruntables;
} abst_t;

#ifdef __cplusplus
extern "C" {
#endif

void   destoryAbst(abst_t *abst);
char  *parseAbst(char *buff,abst_t *abst);
int    parseAbstByPath(char *path,abst_t *abst,FILE **fp);
int    create_abst_file(char *path,char *buff,size_t len);
void   repeat_fragmentrunentrycount(FILE *fp,size_t pos,u_int32_t cnt);
void   append_fragmentrunentry(FILE *fp,fragmentrunentry_t *entry);

size_t    create_token(u_char **p);
u_int64_t parse_token(u_char *str,size_t len);

#ifdef __cplusplus
}
#endif
#endif //PARSE_ABST_H
